package com.gitee.cirnochat.login.controller;

import com.gitee.cirnochat.common.annotation.AuthCheck;
import com.gitee.cirnochat.common.model.vo.resp.Result;
import com.gitee.cirnochat.common.service.QrCodeService;
import com.gitee.cirnochat.common.utils.RequestUtils;
import com.gitee.cirnochat.login.model.vo.req.UserEmailCodeLoginRequest;
import com.gitee.cirnochat.login.model.vo.req.UserEmailPasswordLoginRequest;
import com.gitee.cirnochat.login.model.vo.resp.LoginQrCodeStatusVo;
import com.gitee.cirnochat.login.service.UserLoginService;
import com.gitee.cirnochat.user.model.vo.resp.UserVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseCookie;
import org.springframework.web.bind.annotation.*;

@Tag(name = "用户登录接口", description = "用户登录相关API")
@RestController
@RequestMapping("/user/login")
@RequiredArgsConstructor
@Slf4j
public class UserLoginController {
    private final UserLoginService userLoginService;
    private final QrCodeService qrCodeService;

    /**
     * 邮箱+验证码登录或注册
     *
     * @param req   登录信息
     * @param request  请求
     * @param response 响应
     * @return 登录结果
     */
    @Operation(summary = "邮箱验证码登录或注册", description = "用户通过邮箱和验证码进行登陆，如果未注册则本次会自动注册,accessToken过期时间为30分钟")
    @PostMapping("/email/code")
    @ApiResponse(
            responseCode = "200",
            description = "成功",
            content = @Content(
                    mediaType = "application/json",
                    schema = @Schema(implementation = UserVo.class)
            )
    )
    @Parameter(name = "X-Device-Id", description = "设备ID", required = true , in = ParameterIn.HEADER)
    @Parameter(name = "X-Device-Name", description = "设备名称", required = true , in = ParameterIn.HEADER)
    @Parameter(name = "X-Device-Type", description = "设备类型", required = true , in = ParameterIn.HEADER)
    public Result<UserVo> emailCodeLogin(@Valid @RequestBody UserEmailCodeLoginRequest req,
                                         @RequestHeader("X-Device-Id") String deviceId,
                                         HttpServletRequest request,
                                         HttpServletResponse response) {
        return Result.success(userLoginService.emailCodeLogin(req,deviceId,
                userId -> request.setAttribute("user", userId),
                (ak, sk, refreshTokenExpireTime) -> {
                    // 设置响应头和 Cookie
                    response.setHeader("Authorization", ak);
                    // 将 refreshToken 放入 HttpOnly Cookie
                    ResponseCookie cookie = ResponseCookie.from("refresh_token", sk)
                            .httpOnly(true)  // 关键设置：防止 XSS 读取
                            .secure(true)    // 如果是 HTTPS，建议加上
                            .path("/")       // 全路径有效
                            .maxAge(refreshTokenExpireTime)
                            .build();
                    response.setHeader("Set-Cookie", cookie.toString());
                }));
    }

    /**
     * 邮箱密码登录
     *
     * @param req      登录信息
     * @param request  请求
     * @param response 响应
     * @return 登录结果
     */
    @Operation(summary = "邮箱密码登录", description = "用户通过邮箱和密码进行登陆，如果未注册则本次会自动注册,accessToken过期时间为30分钟")
    @PostMapping("/email/pass")
    @ApiResponse(
            responseCode = "200",
            description = "成功",
            content = @Content(
                    mediaType = "application/json",
                    schema = @Schema(implementation = UserVo.class)
            )
    )
    @Parameter(name = "X-Device-Id", description = "设备ID", required = true , in = ParameterIn.HEADER)
    @Parameter(name = "X-Device-Name", description = "设备名称", required = true , in = ParameterIn.HEADER)
    @Parameter(name = "X-Device-Type", description = "设备类型", required = true , in = ParameterIn.HEADER)
    public Result<UserVo> emailPasswordLogin(@Valid @RequestBody UserEmailPasswordLoginRequest req,
                                             @RequestHeader("X-Device-Id") String deviceId,
                                             HttpServletRequest request,
                                             HttpServletResponse response) {
        return Result.success(userLoginService.emailPasswordLogin(req,deviceId,
                userId -> request.setAttribute("user", userId),
                (ak, sk, refreshTokenExpireTime) -> {
                    // 设置响应头和 Cookie
                    response.setHeader("Authorization", ak);
                    // 将 refreshToken 放入 HttpOnly Cookie
                    ResponseCookie cookie = ResponseCookie.from("refresh_token", sk)
                            .httpOnly(true)  // 关键设置：防止 XSS 读取
                            .secure(true)    // 如果是 HTTPS，建议加上
                            .path("/")       // 全路径有效
                            .maxAge(refreshTokenExpireTime)
                            .build();
                    response.setHeader("Set-Cookie", cookie.toString());
                }));
    }


    /**
     * 刷新token
     *
     * @param request  请求
     * @param response 响应
     * @return 登录结果
     */
    @Operation(summary = "刷新token", description = "刷新token")
    @ApiResponse(
            responseCode = "200",
            description = "成功",
            content = @Content(
                    mediaType = "application/json",
                    schema = @Schema(implementation = Result.class)
            )
    )
    @GetMapping("/auth/refresh_token")
    @Parameter(name = "X-Device-Id", description = "设备ID", required = true , in = ParameterIn.HEADER)
    public Result<Void> refreshToken(HttpServletRequest request,
                                     @RequestHeader("X-Device-Id") String deviceId,
                                     HttpServletResponse response) {
        Long userId = RequestUtils.getUserId(request);
        Cookie[] cookies = request.getCookies();
        String refreshToken = null;
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if ("refresh_token".equals(cookie.getName())) {
                    refreshToken = cookie.getValue();
                    break;
                }
            }
        }
        userLoginService.refreshToken(refreshToken,userId,deviceId, ak -> response.setHeader("Authorization", ak));
        return Result.success();
    }

    /**
     * 用户登出
     *
     * @param request  请求
     * @param response 响应
     * @return 登出结果
     */
    @Operation(summary = "用户登出", description = "清除双TOKEN并清除Cookie")
    @ApiResponse(
            responseCode = "200",
            description = "成功",
            content = @Content(
                    mediaType = "application/json",
                    schema = @Schema(implementation = Result.class)
            )
    )
    @AuthCheck
    @Parameter(name = "Authorization", description = "认证信息", required = true , in = ParameterIn.HEADER)
    @Parameter(name = "X-Device-Id", description = "设备ID", required = true , in = ParameterIn.HEADER)
    @DeleteMapping("/logout")
    public Result<Void> logout(HttpServletRequest request, @RequestHeader("X-Device-Id") String deviceId, HttpServletResponse response) {
        Long userId = RequestUtils.getUserId(request);
        userLoginService.logout(userId, deviceId, () -> {
            // 清除Cookie
            Cookie refreshTokenCookie = new Cookie("refresh_token", null);
            refreshTokenCookie.setMaxAge(0);
            refreshTokenCookie.setPath("/");
            response.addCookie(refreshTokenCookie);
        });
        return Result.success();
    }


    @Operation(summary = "生成登录二维码", description = "生成一个用于登录的二维码")
    @GetMapping("/qrcode/generate")
    @Parameter(name = "X-Device-Id", description = "设备ID", required = true , in = ParameterIn.HEADER)
    @Parameter(name = "X-Device-Name", description = "设备名称", required = true , in = ParameterIn.HEADER)
    @Parameter(name = "X-Device-Type", description = "设备类型", required = true , in = ParameterIn.HEADER)
    public Result<LoginQrCodeStatusVo> generateQrCode(HttpServletRequest request) {
        return Result.success(qrCodeService.generateLoginQrCode(request));
    }

    @Operation(summary = "查询登录二维码状态", description = "查询二维码的登录状态")
    @GetMapping("/qrcode/status/{qrCodeId}")
    @Parameter(name = "X-Device-Id", description = "设备ID", required = true , in = ParameterIn.HEADER)
    public Result<LoginQrCodeStatusVo> getQrCodeStatus(@PathVariable String qrCodeId,HttpServletRequest request) {
        return Result.success(qrCodeService.getLoginQrCodeStatus(qrCodeId,request));
    }

    @Operation(summary = "查询登录二维码登陆结果", description = "查询二维码的登录状态")
    @GetMapping("/qrcode/result/{qrCodeId}")
    @Parameter(name = "X-Device-Id", description = "设备ID", required = true , in = ParameterIn.HEADER)
    @Parameter(name = "X-Device-Name", description = "设备名称", required = true , in = ParameterIn.HEADER)
    @Parameter(name = "X-Device-Type", description = "设备类型", required = true , in = ParameterIn.HEADER)
    public Result<UserVo> getQrCodeResult(@PathVariable String qrCodeId,
                                          @RequestHeader("X-Device-Id") String deviceId,
                                          HttpServletRequest request ,
                                          HttpServletResponse response) {
        return Result.success(userLoginService.getLoginQrCodeResult(qrCodeId,deviceId,
                userId -> request.setAttribute("user", userId),
                (ak, sk, refreshTokenExpireTime) -> {
                    // 设置响应头和 Cookie
                    response.setHeader("Authorization", ak);
                    // 将 refreshToken 放入 HttpOnly Cookie
                    ResponseCookie cookie = ResponseCookie.from("refresh_token", sk)
                            .httpOnly(true)  // 关键设置：防止 XSS 读取
                            .secure(true)    // 如果是 HTTPS，建议加上
                            .path("/")       // 全路径有效
                            .maxAge(refreshTokenExpireTime)
                            .build();
                    response.setHeader("Set-Cookie", cookie.toString());
                }));
    }


    @Operation(summary = "扫描二维码登录", description = "通过扫描二维码完成登录")
    @PostMapping("/qrcode/scan/{qrCodeId}")
    @Parameter(name = "Authorization", description = "用户的访问令牌", required = true, in = ParameterIn.HEADER)
    @Parameter(name = "X-Device-Id", description = "设备ID", required = true , in = ParameterIn.HEADER)
    @AuthCheck
    public Result<Void> scanQrCodeLogin(@PathVariable String qrCodeId, HttpServletRequest request) {
        Long userId = RequestUtils.getUserId(request);
        userLoginService.scanQrCodeLogin(qrCodeId,userId);
        return Result.success();
    }

}
